package com.wushi.codegen;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import com.wushi.codegen.base.ColunmsClass;
import com.wushi.codegen.base.TableClass;

import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import freemarker.template.TemplateExceptionHandler;

/**
 * @author heitu
 *
 */
@Component
public class CodeGenerator {
	
	@Autowired
	private JdbcTemplate jdbc;
	
	//@Value("/Users/heitu/git/repository/GrantJavaTools/src/main/resources/template")
	 @Value("${template.path}")   //@value 里面使用spring el 可从properties里面读取数据，或者直接赋值
	private String templatePath;
	 @Value("${sourceTarget.path}")
	private String sourceTargetPath;
	 @Value("${source.package}")
	private Object packagePath;

	/*
	 * @Input table name
	 * return the meta data for the table and columns
	 * @out root: include the table name	
	 */
	public Map<String,Object> getDBmetadata(String tableName) {
		Map<String, Object> root=new HashMap<String, Object>();
		HashMap<String, ColunmsClass> fields=new HashMap<String, ColunmsClass>();  //bean fields,经过转义的列meta data
		HashMap<String, String> fieldColMap=new HashMap<String, String>();  //表格列name与field 之间的映射，field<->column name
		String tableOriginalName=null;
		
		TableClass table=new TableClass();
		try { //根据JDBCTemplate获取DataSource，然后根据Connection获取MetaData对象
			DatabaseMetaData metaData = jdbc.getDataSource().getConnection().getMetaData();
			ResultSet tables = metaData.getTables(null, "%", tableName, null);   //获取某个表的meata data
			//取得表格的metaData, 包括 TABLE_NAME,REMARKS
			while(tables.next()) {
				table.setName(StringUtils.replace(tables.getString("TABLE_NAME"),"_","")); 	 //删除表列明中的"_"
				table.setRemark(tables.getString("REMARKS"));
				
				tableOriginalName=tables.getString("TABLE_NAME");
			}
			
			System.out.println("#####table:"+table.toString());
			//取得此表所有列的metaData,包括 COLUMN_NAME,TYPE_NAME, REMARKS
			ResultSet columns = metaData.getColumns(null, "%", tableName, "%");
			while(columns.next()) {
	            if(columns.getString("COLUMN_NAME").equals("id")) continue;
	            ColunmsClass column=new ColunmsClass();
	            column.setName(StringUtils.replace(columns.getString("COLUMN_NAME"),"_","")); 	 //删除表列明中的"_"
	            column.setType(changeDataType(columns.getString("TYPE_NAME")));
	            column.setRemark(columns.getString("REMARKS"));
	            fields.put(column.getName(), column);
	            System.out.println("######field:"+column.toString());
	            
	            fieldColMap.put(column.getName(), columns.getString("COLUMN_NAME"));  
			}
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		if (fields.size()<=0)
				return null;
		else {
			//讲table 和 columns的metadata 放入root对象中，并返回
			root.put("fields", fields); 
			root.put("fieldColMap", fieldColMap); 
			root.put("table", table);   //table已经被转成class name
			root.put("tableOriginalName", tableOriginalName);   //真实的table name
			root.put("package", packagePath);
			return root;
		}
		
	}
	
//mysql列数据类型转换为java数据类型，如tinyint->Integer， deciaml->float
	public String changeDataType(String column_type){
		String result=column_type;
		if("varchar".equals(column_type)) {
			result="String";
		}else if("tinyint".equals(column_type)){
			result="int";
		}else if("smallint".equals(column_type)){
			result="int";
		}else if("decimal".equals(column_type)) {
			result="float";
		}else if("datetime".equals(column_type) || "timestamp".equals(column_type)){
			result="Date";
		}
		return result;
	}
	
	//根据Freemaker模板产生Entity
	public boolean generateEntity(Map<String, Object> root) throws IOException {
		File javaFile;
		BufferedWriter writer=null;
		
		if(root==null)
			return false;
		//Freemaker 在写之前需要配置参数，通过Configuration实现
		Configuration config=new Configuration(Configuration.VERSION_2_3_28);
		try {
			config.setDirectoryForTemplateLoading(new File(templatePath));
			config.setDefaultEncoding("UTF-8");
			config.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
			config.setLogTemplateExceptions(false);
			config.setWrapUncheckedExceptions(true);
			Template template = config.getTemplate("entity.ftl");
			TableClass table=(TableClass)root.get("table"); 
			//外部java文件对象，后续需要根据常量配置路径
			javaFile=new File(sourceTargetPath,StringUtils.capitalize(table.getName())+".java");
			if(!javaFile.exists())
				javaFile.createNewFile();   //java file不存在时显示创建这个文件
			writer = new BufferedWriter(new FileWriter(javaFile));
			template.process(root, writer); 
			return true;
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return false;
		} catch (TemplateException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return false;
		}finally {
			writer.close();
		
		}
		
	}
	
	
	//根据Freemaker模板产生Mapper.xml
		public boolean generateMapper(Map<String, Object> root) throws IOException {
			File mapperFile;
			BufferedWriter writer=null;
			
			if(root==null)
				return false;
			//Freemaker 在写之前需要配置参数，通过Configuration实现
			Configuration config=new Configuration(Configuration.VERSION_2_3_28);
			try {
				config.setDirectoryForTemplateLoading(new File(templatePath));
				config.setDefaultEncoding("UTF-8");
				config.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
				config.setLogTemplateExceptions(false);
				config.setWrapUncheckedExceptions(true);
				Template template = config.getTemplate("mapper.ftl");
				TableClass table=(TableClass)root.get("table"); 
				//外部mapper文件对象，后续需要根据常量配置路径
				mapperFile=new File(sourceTargetPath,StringUtils.capitalize(table.getName())+"Mapper.xml");
				if(!mapperFile.exists())
					mapperFile.createNewFile();   //java file不存在时显示创建这个文件
				writer = new BufferedWriter(new FileWriter(mapperFile));
				template.process(root, writer); 
				return true;
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				return false;
			} catch (TemplateException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				return false;
			}finally {
				writer.close();
			
			}
			
		}

	public static void main(String[] args) {

	
	}

}
